package cn.wizzer.app.user.modules.service.impl;

import cn.wizzer.app.sys.modules.models.SysParam;
import cn.wizzer.app.sys.modules.services.SysParamService;
import cn.wizzer.app.user.modules.models.UserChatMsg;
import cn.wizzer.app.user.modules.models.enums.MsgStatusEnum;
import cn.wizzer.app.user.modules.models.enums.MsgTypeEnum;
import cn.wizzer.app.user.modules.models.vo.ChatUserMsgVO;
import cn.wizzer.app.user.modules.services.UserChatMsgService;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.base.service.CommonDBService;
import cn.wizzer.framework.page.Pagination;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.*;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@IocBean(args = {"refer:dao"})
@Service(interfaceClass = UserChatMsgService.class)
public class UserChatMsgServiceImpl extends BaseServiceImpl<UserChatMsg> implements UserChatMsgService {
    public UserChatMsgServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private CommonDBService dbService;
    @Inject
    @Reference
    private SysParamService sysParamService;

    @Override
    public Pagination listPage(int pageNumber, int pageSize, String sender, String receiver, String[] searchDate, MsgTypeEnum type, MsgStatusEnum status) {
        Sql sql = Sqls.create("select fu.nickname fromUserNickname,fu.username fromUsername,tu.nickname toUserNickname,tu.username toUsername, m.* " +
                "from user_chat_msg m");
        Sql countSql = Sqls.create("select count(1) count " +
                "from user_chat_msg m");
        String leftSqlStr = "left join user fu on fu.id = m.userId " +
                "left join user tu on tu.id = m.toUser " +
                "where m.delFlag = 0 ";
        sql.appendSourceSql(leftSqlStr);
        countSql.appendSourceSql(leftSqlStr);
        if (Strings.isNotBlank(sender)) {
            String sqlStr = "and (fu.nickName like concat('%', @sender, '%') " +
                    "or fu.email like concat('%', @sender, '%') " +
                    "or fu.userName like concat('%', @sender, '%'))";
            sql.appendSourceSql(sqlStr);
            sql.setParam("sender", sender);
            countSql.appendSourceSql(sqlStr);
            countSql.setParam("sender", sender);
        }
        if (Strings.isNotBlank(receiver)) {
            String sqlStr = "and (tu.nickName like concat('%', @receiver, '%') " +
                    "or tu.email like concat('%', @receiver, '%') " +
                    "or tu.userName like concat('%', @receiver, '%'))";
            sql.appendSourceSql(sqlStr);
            sql.setParam("receiver", receiver);
            countSql.appendSourceSql(sqlStr);
            countSql.setParam("receiver", receiver);
        }
        if (searchDate != null && searchDate.length != 0) {
            String sqlStr = "and m.ctAt >= @startTime " +
                    "and m.ctAt <= @endTime ";
            sql.appendSourceSql(sqlStr);
            sql.setParam("startTime", Times.d2TS(Times.D(searchDate[0])));
            sql.setParam("endTime", Times.d2TS(Times.D(searchDate[1])));
            countSql.appendSourceSql(sqlStr);
            countSql.setParam("startTime", Times.d2TS(Times.D(searchDate[0])));
            countSql.setParam("endTime", Times.d2TS(Times.D(searchDate[1])));
        }
        if (type != null) {
            String sqlStr = "and m.type = @type";
            sql.appendSourceSql(sqlStr);
            sql.setParam("type", type);
            countSql.appendSourceSql(sqlStr);
            countSql.setParam("type", type);
        }
        if (status != null) {
            String sqlStr = "and m.status = @status";
            sql.appendSourceSql(sqlStr);
            sql.setParam("status", status);
            countSql.appendSourceSql(sqlStr);
            countSql.setParam("status", status);
        }
        sql.appendSourceSql("order by m.ctAt desc");
        return dbService.listPage(ChatUserMsgVO.class, pageNumber, pageSize, sql.toString(), countSql.toString());
    }

    /**
     * 查询最近聊天用户
     *
     * @param userId
     * @return
     */
    @Override
    @Aop(TransAop.READ_COMMITTED)
    public List<String> findRecentChatUser(String userId) {
        Sql sql = Sqls.create("SELECT m.id, m.userId " +
                "FROM (SELECT userId, MAX(ctAt) ctAt " +
                "   FROM user_chat_msg GROUP BY userId) c " +
                "LEFT JOIN user_chat_msg m ON m.userId = c.userId AND m.ctAt = c.ctAt " +
                "$condition AND m.delFlag = 0 " +
                "ORDER BY m.ctAt DESC");
        sql.setCondition(Cnd.where("m.toUser", "=", userId));
        List<UserChatMsg> chatMsgList = this.listEntity(sql);
        List<String> users = new ArrayList<>();
        if(chatMsgList.size() > 0){
            users = chatMsgList.stream().map(UserChatMsg::getUserId).collect(Collectors.toList());
        }
        //查询留言用户，修改接收者为客服自己
        sql.setCondition(Cnd.where("m.toUser", "IS", null));
        chatMsgList = this.listEntity(sql);
        if(chatMsgList.size() > 0){
            List<String> updateIds = new ArrayList<>(chatMsgList.size());
            for (UserChatMsg userChatMsg : chatMsgList) {
                users.add(userChatMsg.getUserId());
                updateIds.add(userChatMsg.getId());
            }
            this.update(Chain.make("toUser", userId), Cnd.where("id", "IN", updateIds));
        }
        return users;
    }

    @Override
    public Pagination listPage(int pageNumber, int pageSize, String userId) {
        Sql sql = Sqls.create("SELECT fu.nickname fromUserNickname,fu.headPicture as fromUserPicture, " +
                "tu.nickname toUserNickname,tu.headPicture as toUserPicture, " +
                "m.id, m.userId, m.toUser, m.ctAt, m.type, m.status, m.content " +
                "FROM user_chat_msg m " +
                "LEFT JOIN user fu ON m.userId = fu.id " +
                "LEFT JOIN user tu ON m.toUser = tu.id " +
                "$condition " +
                "ORDER BY m.ctAt DESC");
        Sql countSql = Sqls.create("SELECT COUNT(1) FROM user_chat_msg m " +
                "$condition ");
        Cnd cnd = Cnd.where("m.status", "IN", new MsgStatusEnum[]{MsgStatusEnum.UN_READ, MsgStatusEnum.READ})
                .and(Cnd.exps("m.userId", "=", userId).or("m.toUser", "=", userId));
        sql.setCondition(cnd);
        countSql.setCondition(cnd);
        return dbService.listPage(ChatUserMsgVO.class, pageNumber, pageSize, sql.toString(), countSql.toString());
    }

    @Override
    public void delMsgJob() {
        SysParam sysParam = sysParamService.fetch();
        //全局参数获取客服聊天记录保存天数
        Double keepDayNumber = sysParam.getUserChatMsgKeepDayNumber();
        //天数大于0时计算删除一定时间前的记录
        if(keepDayNumber > 0){
            //保存时间
            long keepTimestamp = new Double(keepDayNumber * 24 * 60 * 60).longValue();
            //保存开始时间 = 当前时间 - 保存时间
            long keepStartTime = Times.getTS() - keepTimestamp;
            //查询保存开始时间之前的记录后删除记录
//            List<UserChatMsg> userChatMsgList = this.query(Cnd.where("ctAt", "<=", keepStartTime));
//            this.delete(userChatMsgList.stream().map(UserChatMsg::getId).collect(Collectors.toList()));
            //删除保存时间开始之前的记录
            this.clear(Cnd.where("ctAt", "<=", keepStartTime));
        }
    }

    @Override
    public String attendantUnreadNum(String appid) {
        Sql sql = Sqls.create("SELECT COUNT(*) FROM user_chat_msg WHERE toUser = @userId and status = 'UN_READ'");
        sql.setParam("userId", appid);
        sql.setCallback(Sqls.callback.str());
        this.dao().execute(sql);
        return sql.getString();
    }
}
